From: Keir Fraser Date: Sun, 3 Feb 2008 09:30:59 +0000 (+0000) Subject: vmx realmode: HOST_CR0.TS must be cleared when restoring guest FPU X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~14341^2~5 X-Git-Url: https://dgit.raspbian.org/%22http:/www.example.com/cgi/%22https:/%22bookmarks://%22Dat/%22http:/www.example.com/cgi/%22https:/%22bookmarks:/%22Dat?a=commitdiff_plain;h=b2e1b25f9c4c43c3eff31d5fd63fb294bc4c3e96;p=xen.git vmx realmode: HOST_CR0.TS must be cleared when restoring guest FPU state, otherwise in-Xen CR0.TS value becomes set again on next vmexit. Then we crash the next time we try to emulate an FPU instruction. Signed-off-by: Keir Fraser --- diff --git a/xen/arch/x86/hvm/vmx/vmcs.c b/xen/arch/x86/hvm/vmx/vmcs.c index 4ecbccef66..079b673f9c 100644 --- a/xen/arch/x86/hvm/vmx/vmcs.c +++ b/xen/arch/x86/hvm/vmx/vmcs.c @@ -489,7 +489,8 @@ static int construct_vmcs(struct vcpu *v) __vmwrite(HOST_GS_BASE, 0); /* Host control registers. */ - __vmwrite(HOST_CR0, read_cr0() | X86_CR0_TS); + v->arch.hvm_vmx.host_cr0 = read_cr0() | X86_CR0_TS; + __vmwrite(HOST_CR0, v->arch.hvm_vmx.host_cr0); __vmwrite(HOST_CR4, mmu_cr4_features); /* Host CS:RIP. */ diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index 05dba05116..aa46de1548 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -742,6 +742,13 @@ static int vmx_load_vmcs_ctxt(struct vcpu *v, struct hvm_hw_cpu *ctxt) static void vmx_ctxt_switch_from(struct vcpu *v) { + ASSERT(read_cr0() & X86_CR0_TS); + if ( !(v->arch.hvm_vmx.host_cr0 & X86_CR0_TS) ) + { + v->arch.hvm_vmx.host_cr0 |= X86_CR0_TS; + __vmwrite(HOST_CR0, v->arch.hvm_vmx.host_cr0); + } + vmx_save_guest_msrs(v); vmx_restore_host_msrs(); vmx_save_dr(v); @@ -1232,6 +1239,10 @@ void vmx_do_no_device_fault(void) setup_fpu(current); __vm_clear_bit(EXCEPTION_BITMAP, TRAP_no_device); + ASSERT(v->arch.hvm_vmx.host_cr0 & X86_CR0_TS); + v->arch.hvm_vmx.host_cr0 &= ~X86_CR0_TS; + __vmwrite(HOST_CR0, v->arch.hvm_vmx.host_cr0); + /* Disable TS in guest CR0 unless the guest wants the exception too. */ if ( !(v->arch.hvm_vcpu.guest_cr[0] & X86_CR0_TS) ) { diff --git a/xen/include/asm-x86/hvm/vmx/cpu.h b/xen/include/asm-x86/hvm/vmx/cpu.h index c988b13343..decd01e829 100644 --- a/xen/include/asm-x86/hvm/vmx/cpu.h +++ b/xen/include/asm-x86/hvm/vmx/cpu.h @@ -19,19 +19,6 @@ #ifndef __ASM_X86_HVM_VMX_CPU_H__ #define __ASM_X86_HVM_VMX_CPU_H__ -/* - * Virtual CPU - */ -struct arch_state_struct { - unsigned long mode_flags; /* vm86, 32-bit, 64-bit, etc. */ - /* debug registers */ - /* MSRs */ -}; - -#define VMX_MF_VM86 0 -#define VMX_MF_32 1 -#define VMX_MF_64 2 - #define NUM_CORES_RESET_MASK 0x00003FFF #define NUM_THREADS_RESET_MASK 0xFF00FFFF diff --git a/xen/include/asm-x86/hvm/vmx/vmcs.h b/xen/include/asm-x86/hvm/vmx/vmcs.h index 2b92b30446..7f8080739c 100644 --- a/xen/include/asm-x86/hvm/vmx/vmcs.h +++ b/xen/include/asm-x86/hvm/vmx/vmcs.h @@ -92,6 +92,8 @@ struct arch_vmx_struct { unsigned int host_msr_count; struct vmx_msr_entry *host_msr_area; + unsigned long host_cr0; + #ifdef VMXASSIST unsigned long vmxassist_enabled:1; unsigned long irqbase_mode:1;